package cn.com.header.zbpk.web.security;

import cn.com.header.core.support.web.JsonViewData;
import cn.com.header.core.support.web.RequestUtil;
import cn.com.header.core.support.web.ResultCode;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.session.SessionInformationExpiredEvent;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Session管理策略器
 *
 * @author Liangzhongqiu
 * @date 2017-10-19
 * @time 20:56
 */
public class AsyncCompatibleSessionManagementStrategy implements InvalidSessionStrategy, SessionInformationExpiredStrategy {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private final String destinationUrl;
    private final RedirectStrategy redirectStrategy;
    @Setter
    private boolean createNewSession = true;

    public AsyncCompatibleSessionManagementStrategy(String invalidSessionOrExpiredUrl) {
        this(invalidSessionOrExpiredUrl, new DefaultRedirectStrategy());
    }

    public AsyncCompatibleSessionManagementStrategy(String invalidSessionOrExpiredUrl, RedirectStrategy redirectStrategy) {
        Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionOrExpiredUrl),
                "url must start with '/' or with 'http(s)'");
        this.destinationUrl = invalidSessionOrExpiredUrl;
        this.redirectStrategy = redirectStrategy;
    }

    /**
     * session 不存在
     *
     * @param request  请求对象
     * @param response 响应对象
     * @throws IOException      I/O异常
     * @throws ServletException Servlet容器异常
     */
    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        logger.debug("Starting new session (if required) and redirecting to '"
                + destinationUrl + "'");
        if (createNewSession) {
            request.getSession();
        }
        if (RequestUtil.isAjax(request)) {
            JsonViewData.NO_LOGIN_VIEW.write(response);
            return;
        }
        redirectStrategy.sendRedirect(request, response, destinationUrl);
    }

    /**
     * Session过期（多次登录）
     *
     * @param event 过期Session信息事件
     * @throws IOException      I/O异常
     * @throws ServletException Servlet容器异常
     */
    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
        if (RequestUtil.isAjax(event.getRequest())) {
            new JsonViewData(ResultCode.NO_LOGIN, "账号已在其他地方登录，被挤下线！").write(event.getResponse());
            return;
        }
        redirectStrategy.sendRedirect(event.getRequest(), event.getResponse(), destinationUrl);
    }
}
